因為Shadow DOM把內部的DOM和外部的DOM分開了。所以CSS選擇器沒辦法從外部正常的使用在Shadow DOM的內部節點上。也因此,CSS的使用一直以來都是件麻煩的事情
在所有設定Shadow DOM CSS的方法中,最簡單也最常用的方法就是把CSS用style元素包起來後放入web component之中。但這種方式只能設定固定的CSS,會受限於客製化。
Web API中有一個名稱為"CSSStyleSheet"的物件,可以更系統化的寫入CSS,通常是用來設計library。
Shadow DOM的限制只有選擇器無法使用。但CSS還是有些不用選擇器就能做出部分客製化的方法。
inherit可以繼承父節點的參數。Shadow DOM內部的節點也可以繼承到web component根節點的參數。
如果說有什麽CSS 的設計可以讓全CSSOM都能使用,那就是CSS變數了。就算在Shadow DOM以外的部分設定CSS 變數,Shadow DOM內部的節點還是能使用CSS 變數。
本偽類只能在Shadow DOM內使用,使用起來就像是Shadow DOM 的':root'
直接把CSS寫入web compoent之中只適合不會變動的CSS,而使用inherit、CSS變數之類的方法能客製化的地方也很有限,如果需要動畫之類的即時效果,還是使用 web component 的屬性,再用監聽的屬性的方法來動態修改 inline style。
HTML
<body>
<main>
<my-com id="my-com" content-color="yellow">
<div id="slot">click</div>
</my-com>
</main>
</body>
CSS
#slot {
color: blue;
}
body {
color: purple;
--card-content-color: red;
}
Javascript
class MyComponent extends HTMLElement {
root = null
style = `
.card-title {
color: inherit;
}
.card-content {
color: var(--card-content-color, inherit)
}
`
constructor() {
super();
this.render = this.render.bind(this);
this.root = this.attachShadow({mode: 'open'});
this.root.appendChild(this.render())
}
static get observedAttributes() {
return ['content-color'];
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'content-color') {
this.root.getElementById('card-content2').style.color = newValue;
}
}
render() {
const template = document.createElement('template');
//直接把固定的css寫入style元素之中
template.innerHTML = `
<style>${this.style}</style>
<div class='card'>
<h2 id='card-title' class='card-title'>title</h2>
<div id='card-content' class='card-content'>content</div>
<div id='card-content2' class='card-content2'>content2</div>
<slot id='card-slot'></slot>
</div>
`;
return template.content;
//因為有寫inherit,'title'字體顏色為purple
//因為有使用CSS變數,'content'字體顏色為red
//因為有使用inline style,'content2'字體顏色為yellow
//會同時使用web cpmponent 和slot的設定,'click'字體顏色為blue
}
}
customElements.define('my-com', MyComponent);